package com.hgw.imsever.netty.handler;

import com.alibaba.fastjson.JSONObject;
import com.hgw.imsever.common.RedisKeyConsts;
import com.hgw.imsever.common.utils.RedisUtil;
import com.hgw.imsever.netty.ChannelGroupMap;
import com.hgw.imsever.netty.enums.MessageTypeEnum;
import com.hgw.imsever.netty.task.UserOfflineTask;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 心跳机制
 */
@Slf4j
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

    private RedisUtil redisUtil;

    public HeartBeatHandler(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg != null && msg instanceof BinaryWebSocketFrame) {
            BinaryWebSocketFrame webSocketFrame = (BinaryWebSocketFrame) msg;
            ByteBuf content = webSocketFrame.content();
            if (content.readableBytes() > 0) {
                String data = webSocketFrame.content().toString(CharsetUtil.UTF_8);
                try {
                    JSONObject parseObject = JSONObject.parseObject(data);
                    Integer messageType = parseObject.getInteger("messageType");
                    if (messageType != null && MessageTypeEnum.KEEP_ALIVE.getCode() == messageType) {
                        log.info("heart beat received...........");
                    }
                } catch (Exception e) {
                    log.error("error msg: {},error data: {}", e.getMessage(), data);
                    e.printStackTrace();
                }
            }
        }
        super.channelRead(ctx, msg);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                String channelId = ctx.channel().id().asLongText();
                log.info("{} not receive reader event.......disconnect",channelId);
                //todo 从Redis中取出通道Id和用户id对应数据
                String userId = redisUtil.hget(RedisKeyConsts.CHAT_CHANNEL_USER, channelId);
                //移除对应channel
                ChannelGroupMap.channelMap.remove(userId);
                ctx.channel().eventLoop().submit(new UserOfflineTask(channelId, userId, redisUtil));
                //规定时间没有数据读取事件，断开连接
                ctx.disconnect();
            }
        }
        super.userEventTriggered(ctx, evt);
    }
}
